package com.zsj.juc.interrupt;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author zsj
 * @version 1.0
 * @date 2024/4/20 14:39
 * @description 中断机制
 */

public class InterruptDemo {
    static volatile boolean isStop = false;

    static AtomicBoolean atomicBoolean = new AtomicBoolean(false);

    public static void main(String[] args) {
        //此方法只是将线程的中断状态设置为true 并不是真正的将线程干掉了 实例方法
//        Thread.currentThread().interrupt();
        //返回当前线程是否被中断 且去清除中断状态 将其重置为false  静态方法
//        System.out.println(Thread.interrupted());
        //判断当前线程是否被中断 实例方法
//        System.out.println(Thread.currentThread().isInterrupted());

        //为什么 这里isStop没有添加volatile修饰 也会被t1线程给识别到变量更新了呢？
        /**
         * 因为println底层有个synchronized方法 它会改变可见性
         * 空循环也会造成编译器优化 空循环将会不起作用
         */
        new Thread(() -> {
            while (true) {
                if (isStop) {
                    System.out.println(Thread.currentThread().getName() + "线程停止 因为有线程修改了值");
                    break;
                }
                System.out.println("hello volatile");
            }
        }, "t1").start();
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            isStop = true;
        }, "t2").start();
    }

    private void importantCheck() {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + "中断标志位" +
                            Thread.interrupted());
                    break;
                }
                //终极考点:
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                /*
                   这里为什么要在设置一次线程中断标志位?

                   如果在线程睡眠的时候 收到了 其它线程来修改当前线程的interrupt标志位的话
                   会抛出一个InterruptedException 当发生此异常的时候线程的interrupt标志位会被重置为false
                   所以我们需要在catch块中再次将标志位设置为true

                   可以点开interrupt方法的源码里去查看注释
                 */
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "线程运行中");
            }
        }, "t1");
        t1.start();

        try {
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread t2 = new Thread(t1::interrupt, "t2");
        t2.start();
    }

    private void m1() {
        //此方法只是将线程的中断状态设置为true 并不是真正的将线程干掉了 实例方法
//        Thread.currentThread().interrupt();
        //返回当前线程是否被中断 且去清除中断状态 将其重置为false  静态方法
//        System.out.println(Thread.interrupted());
        //判断当前线程是否被中断 实例方法
//        System.out.println(Thread.currentThread().isInterrupted());

        //为什么 这里isStop没有添加volatile修饰 也会被t1线程给识别到变量更新了呢？
        /**
         * 因为println底层有个synchronized方法 它会改变可见性
         * 空循环也会造成编译器优化 空循环将会不起作用
         */
        new Thread(() -> {
            while (true) {
                if (isStop) {
                    System.out.println(Thread.currentThread().getName() + "线程停止 因为有线程修改了值");
                    break;
                }
                System.out.println("hello volatile");
            }
        }, "t1").start();
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            isStop = true;
        }, "t2").start();
    }

    private void m2() {
        new Thread(() -> {

            while (true) {
                if (atomicBoolean.get()) {
                    System.out.println(Thread.currentThread().getName() + "停止 有线程修改了变量");
                    break;
                }
                System.out.println("t1线程继续执行");
            }
        }, "t1").start();

        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            System.out.println("t2线程开始打断t1线程");
            atomicBoolean.set(true);
        }, "t2").start();

    }

    private void m3() {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("线程中断标志位为" + Thread.interrupted());
                    System.out.println(Thread.currentThread().getName() + "停止 有线程修改了变量");
                    break;
                }
                System.out.println("t1线程继续执行,线程中断标志位为" + Thread.interrupted());
            }
        }, "t1");
        t1.start();

        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            System.out.println("t2线程开始设置t1线程中断标志位");
            t1.interrupt();
        }, "t2").start();
    }

    private void m4() {
          /*
        线程的静态方法interrupted()
        测试当前线程是否已中断。此方法清除线程的中断状态。
        换句话说，如果连续调用此方法两次，则第二次调用将返回false(除非当前线程再次中断，在第一次调用清除其中断状态之后，在第二次调用检查它之前)。
         */
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println("==1");
        Thread.currentThread().interrupt();//设置中断标志位
        System.out.println("==2");
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());

    }
}
